//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __STDIO_H__
#define __STDIO_H__

#include <stddef.h>
#include <stdarg.h>
#include <types.h>
#include <wchar.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef __int64 fpos_t;

#define SEEK_SET    0   /* set FILE offset to offset */
#define SEEK_CUR    1   /* set FILE offset to current plus offset */
#define SEEK_END    2   /* set FILE offset to EOF plus offset */

#define EOF (-1)        /* end-of-file indicator */
#define WEOF (wint_t)(0xFFFF)
#define EOS ('\0')      /* end-of-string indicator */

/*
 * The following three definitions are for ANSI C, which took them
 * from System V, which brilliantly took internal interface macros and
 * made them official arguments to setvbuf(), without renaming them.
 * Hence, these ugly _IOxxx names are *supposed* to appear in user code.
 *
 * Although numbered as their counterparts above, the implementation
 * does not rely on this.
 */
#define _IOFBF  0       /* setvbuf should set fully buffered */
#define _IOLBF  1       /* setvbuf should set line buffered */
#define _IONBF  2       /* setvbuf should set unbuffered */

#define BUFSIZ  1024    /* size of buffer used by setbuf */

/*
 * FOPEN_MAX is a minimum maximum, and should be the number of descriptors
 * that the kernel can provide without allocation of a resource that can
 * fail without the process sleeping.  Do not use this for anything.
 */
#define FOPEN_MAX       20      /* must be <= OPEN_MAX */
#define FILENAME_MAX    260    /* must be <= PATH_MAX */
#define TMP_MAX         32767

struct __sbuf
{
    unsigned char *_base;
    int _size;
};

typedef struct FILE {
    unsigned char *_p;  /* current position in (some) buffer */
    int _r;             /* read space left for getc() */
    int _w;             /* write space left for putc() */
    int _flags;     /* flags, below; this FILE is free if 0 */
    int _file; /* fileno, if Unix descriptor, else -1 */
    struct  __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
    int _lbfsize;       /* 0 or -_bf._size, for inline putc */

    /* operations */
    void    *_cookie;   /* cookie passed to io functions */
    int     (__cdecl *_close)(void *);
    int     (__cdecl *_read)(void *, char *, int);
    fpos_t  (__cdecl *_seek)(void *, fpos_t, int);
    int     (__cdecl *_write)(void *, const char *, int);

    /* separate buffer for long sequences of ungetc() */
    struct  __sbuf _ub; /* ungetc buffer */
    unsigned char *_up; /* saved _p when _p is doing ungetc data */
    int _ur;            /* saved _r when _r is counting ungetc data */

    /* tricks to meet minimum requirements even when malloc() fails */
    unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
    unsigned char _nbuf[2]; /* guarantee a getc() buffer */
                            // reserve 2 bytes for getwc()

    /* separate buffer for fgetln() when line crosses buffer boundary */
    struct  __sbuf _lb;     /* buffer for fgetln() */

    /* Unix stdio files get aligned to block boundaries on fseek() */
    int     _blksize;       /* stat.st_blksize (may be != _bf._size) */
    fpos_t  _offset;        /* current lseek offset */
}FILE;

#ifndef _IOB_
#define _IOB_
extern FILE * __cdecl __p__iob(void);
#define _iob (__p__iob())
#endif

#define stdin   (&_iob[0])
#define stdout  (&_iob[1])
#define stderr  (&_iob[2])

#define win32_stdout (FILE*)((char*)stdin + 0x20)
#define win32_stderr (FILE*)((char*)stdin + 0x40)
#define adjust_std_streams(fp) (fp) == win32_stdout ? stdout \
                             : (fp) == win32_stderr ? stderr : (fp)

#ifndef STRSAFE_NO_DEPRECATE
char *      __cdecl     gets(char *);
int         __cdecl     sprintf(char *, const char *, ...);
int         __cdecl     _snprintf(char *, size_t, const char *, ...);
int         __cdecl     vsprintf(char *, const char *, va_list);
int         __cdecl     _vsnprintf(char *, size_t, const char *, va_list);
int         __cdecl     _scprintf(const char *,...);
int         __cdecl     _vscprintf(const char *, va_list);
wchar_t *   __cdecl     _getws(wchar_t *buf);
int         __cdecl     swprintf(wchar_t *, wchar_t const *, ...);
int         __cdecl     _snwprintf(wchar_t *, size_t, wchar_t const *, ...);
int         __cdecl     vfwprintf(FILE *, const wchar_t *, va_list);
int         __cdecl     _vsnwprintf(wchar_t *, size_t, const wchar_t *, va_list);
int         __cdecl     _scwprintf(const wchar_t *,...);
int         __cdecl     _vscwprintf(const wchar_t *, va_list);
#endif

void        __cdecl     clearerr(FILE *);
int         __cdecl     fclose(FILE *);
int         __cdecl     _fcloseall(void);
int         __cdecl     feof(FILE *);
int         __cdecl     ferror(FILE *);
int         __cdecl     fflush(FILE *);
int         __cdecl     _flushall();
int         __cdecl     fgetc(FILE *);
int         __cdecl     fgetpos(FILE *, fpos_t *);
char *      __cdecl     fgets(char *, int, FILE *);
FILE *      __cdecl     fopen(const char *, const char *);
FILE *      __cdecl     fsopen(const char *, const char *, int);
int         __cdecl     fprintf(FILE *, const char *, ...);
int         __cdecl     fputc(int, FILE *);
int         __cdecl     fputs(const char *, FILE *);
size_t      __cdecl     fread(void *, size_t, size_t, FILE *);
FILE *      __cdecl     freopen(const char *, const char *, FILE *);
FILE *      __cdecl     _wfreopen(const wchar_t *, const wchar_t *, FILE *);
int         __cdecl     fscanf(FILE *, const char *, ...);
int         __cdecl     fseek(FILE *, long, int);
int         __cdecl     fseeko(FILE *, off_t, int);
int         __cdecl     fsetpos(FILE *, const fpos_t *);
long        __cdecl     ftell(FILE *);
off_t       __cdecl     ftello(FILE *);
size_t      __cdecl     fwrite(const void *, size_t, size_t, FILE *);
int         __cdecl     getc(FILE *);
int         __cdecl     getchar(void);
void        __cdecl     rewind(FILE *);
int         __cdecl     remove(const char *);
int         __cdecl     putc(int, FILE *);
int         __cdecl     putchar(int);
int         __cdecl     puts(const char *);
int         __cdecl     _getw(FILE *);
int         __cdecl     _putw(int, FILE *);
int         __cdecl     rename(const char *, const char *);
void        __cdecl     setbuf(FILE *, char *);
int         __cdecl     setvbuf(FILE *, char *, int, size_t);
FILE *      __cdecl     tmpfile(void);
char *      __cdecl     tmpnam(char *);
int         __cdecl     ungetc(int, FILE *);
int         __cdecl     scanf(const char *, ...);
int         __cdecl     sscanf(const char *, const char *, ...);
void        __cdecl     perror(const char *);
int         __cdecl     printf(const char *, ...);
int         __cdecl     vfprintf(FILE *, const char *, va_list);
int         __cdecl     vprintf(const char *, va_list);
int         __cdecl     asprintf(char **, const char *, ...);
int         __cdecl     vasprintf(char **, const char *, va_list);
int         __cdecl     vscanf(const char *, va_list);
int         __cdecl     vsscanf(const char *, const char *, va_list);
int         __cdecl     vfscanf(FILE *, const char *, va_list);
FILE *      __cdecl     _fdopen(int, const char *);
int         __cdecl     _fileno(FILE *);

// wildchar version
FILE *      __cdecl     _wfopen(const wchar_t *, const wchar_t *);
FILE *      __cdecl     _wfsopen(const wchar_t *, const wchar_t *, int);
wchar_t *   __cdecl     fgetws(wchar_t *, int, FILE *);
wint_t      __cdecl     fgetwc(FILE *);
wint_t      __cdecl     getwc(FILE *);
wint_t      __cdecl     getwchar(void);
wint_t      __cdecl     putwc(wint_t, FILE *);
wint_t      __cdecl     putwchar(wint_t);
int         __cdecl     _putws(const wchar_t *);
int         __cdecl     fputws(const wchar_t *, FILE *);
wint_t      __cdecl     fputwc(wint_t, FILE *);
int         __cdecl     fwprintf(FILE *, const wchar_t *, ...);
int         __cdecl     _wremove(const wchar_t *);
int         __cdecl     wprintf(const wchar_t *, ...);
int         __cdecl     vwprintf(const wchar_t *, va_list);
int         __cdecl     vswprintf(wchar_t *, const wchar_t *, va_list);
wint_t      __cdecl     ungetwc(wint_t, FILE *);
FILE *      __cdecl     _wfdopen(int, const wchar_t *);

int         __cdecl     fwscanf(FILE *, const wchar_t *, ...);
int         __cdecl     wscanf(const wchar_t *, ...);
int         __cdecl     swscanf(const wchar_t *, const wchar_t *, ...);
int         __cdecl     vwscanf(const wchar_t *, va_list);
int         __cdecl     vswscanf(const wchar_t *, const wchar_t *, va_list);
int         __cdecl     vfwscanf(FILE *, const wchar_t *, va_list);

//POSIX
int         __cdecl     vsnprintf(char *, size_t, const char *, va_list);
int         __cdecl     snprintf(char *, size_t, const char *, ...);
int         __cdecl     fileno(FILE *);
int         __cdecl     fcloseall(void);
int         __cdecl     getw(FILE *);
int         __cdecl     putw(int, FILE *);
FILE *      __cdecl     fdopen(int, const char *);
char*       __cdecl     fgetln(FILE *, size_t *);

FILE *      __cdecl     _fsopen(const char *, const char *, int);

#ifdef __cplusplus
}
#endif

#endif //__STDIO_H__
